<?php

/**
 * Класс RL_Schema управляет схемой данных.
 *
 * Схема -- набор типов данных
 *
 * методы упрвления схемой:
 *   store      -- сохранить тип в схеме
 *   find       -- веруть известный тип по имени
 *
 * утилиты:
 *   factory    -- создать новый объект типа ...
 * @package RL
 * @author Lucky <lucky@jetstyle.ru>
 * @version $Id: Schema.php 62 2007-09-05 08:27:21Z lucky $
 */
class RL_Schema
{

	/**
	 * types набор типов.
	 *
	 * @var array
	 * @access public
	 */
	public $types = array();

	//!a manipulator
	/**
	 * factory Cоздать новый тип.
	 *
	 * @param mixed $type_name Реальное имя имя типа с точки зрения реализации
	 * @param mixed $alias Псевдоним типа (для использования в контексте приложения)
	 * @access public
	 * @return object RL_Type
	 */
	public function factory ($type_name, $alias=NULL)
	{
		$name = isset($alias) ? $alias : $type_name;

		if (isset($this->types[$type_name])) {
			$o = clone $this->types[$type_name];
		} else {
			// загрузим исходинк с реализацией типа
			$dir    = dirname(__FILE__).'/Type/';
			$script = $dir . $type_name . '.php';
			require_once $script;

			// имя класса (всегда такое)
			$type_class = 'RL_Type_'.$type_name;

			// создать объект типа
			$o = new $type_class();
		}
		if (isset($alias)) $o->parent = $type_name;
		$o->name = $name;
		return $o;
	} //// end of function factory

	//!a manipulator
	/**
	 * store Сохранить тип.
	 *
	 * lucky: FIXME неприкольное название фунции
	 *
	 * @param RL_Type $type
	 * @access public
	 * @return void
	 */
	public function store (RL_Type $type)
	{
		if (array_key_exists($type->name, $this->types)) {
			// не регистрируем один и тот же тип дважды.
			throw new Exception(sprintf('Type %s already exists', $type->name));
		}
		$this->types[$type->name] = $type;
		$type->schema = $this;
		return $this;
	} // end of function setType

	//!a manipulator
	/**
	 * replace Сохранить тип.
	 *
	 * то же самое что store, но может заменить тип, если такой уже создан
	 *
	 * lucky: FIXME что делать с объектами, которым приписан замещаемый тип?
	 *
	 * @param RL_Type $type
	 * @access public
	 * @return void
	 */
	public function replace (RL_Type $type)
	{
		unset ($this->types[$type->name]);
		return $this->store($type);
	} // end of function replace

	//!a manipulator
	/**
	 * find Найти тип по имени.
	 *
	 * @param mixed $name
	 * @access public
	 * @return void
	 */
	public function find ($name)
	{
		return $this->types[$name];
	} // end of function get

}


if (realpath($_SERVER['PHP_SELF']) == __FILE__) {
	// схема
	$sch  = new RL_Schema();


	// базовые типы
	$TString           = $sch->factory('String');

	$TTitle            = $sch->factory('String', 'Title');
	$TTitle->length    = 255;

	$TLogin            = $sch->factory('String', 'Login');
	$TLogin->length    = 20;
	$TLogin->default   = 'anonymous';

	$TPassword         = $sch->factory('String', 'Password');
	$TPassword->length = 10;

	$sch->store($TString);
	$sch->store($TTitle);
	$sch->store($TLogin);

	// тип Юзер
	$TUser = $sch->factory('Object', 'User');
	$TUser->addProperty('login',		$sch->find('Login'));
	$TUser->addProperty('password',	$sch->find('Password'));
	$TUser->addProperty('title',		$sch->find('Title'));
	$sch->store($TUser);

	// Тип автор, то же самое, что Юзер + имя автора
	$TAuthorName = $sch->factory('String', 'AuthorName');
	$TAuthorName->length = 40;
	$sch->store($TAuthorName);

	$TAuthor = $sch->factory('User', 'Author');
	$TAuthor->addProperty('name', $sch->find('AuthorName'));
	$sch->store($TAuthor);

	// Генерим DDL
	require_once (dirname(__FILE__).'/DBAL/Mysql/Schema.php');

	$mysql = new RL_DBAL_Mysql_Schema();
	$mysql->prefix = 'platonica'; // префикс для таблиц

	//$ddl = $mysql->build($sch);
	print($ddl);
}
